const log = require('../../utils/log');
const gameCom = require('../gameCommon/gameCommon');
const gameCfg = require('../../config/gameCfg');
const gameMode = require('../gameCommon/gameMode');
const {Respones,RewardType} = require("../../config/gameCfg");
const CmdZt = require('../proto/CmdZt');
const ModeZt = require('./gameZtModel');
const gameZtCfg = require("./gameZtCfg");
const AlgorZt = require("./algorZt");
const gameZtEnd = require('./gameZtEnd');
const gameZtOpt = require('./gameZtOpt');
const common = require('../../common/common');
const redisBase = require("../../common/RedisBase");

function TopicCur(_uid, _status,_tid,_cid){
    this.idx = 0;
    //答题用户的uid
    this.uid = _uid;
    //状态 0是未答题 1是答对 2是答错
    this.status = _status;
    //题目id
    this.tid = _tid;
    //自己选择的答案id,默认从1开始,例如： 1 2 3 4 表示 答案 1 2 3 4
    this.cid = _cid
}
function UserClient(_uid, _client){
    this.uid = _uid;
    this.client = _client;
    this.reday = false; //标记用户准备状态

    this.curData = null; //记录用户当前题目的操作信息
}

//主题玩法
class GameZt {
    static getInstance(){
        if(!GameZt.instance){
            GameZt.instance = new GameZt();
            return GameZt.instance;
        }else{
            return GameZt.instance;
        }
    }
    constructor() {
        //一组是5题
        this.maxGroupCount = 5;
        //答题时间限制
        this.astrictTime = 10;

        //记录分数限制
        this.timeCfg = [
            {min: 0,max: 1,score: 200},
            {min: 1, max: 2, score: 182},
            {min: 2,max: 3,score: 160},
            {min: 3, max: 4, score: 140},
            {min: 4,max: 5,score: 120},
            {min: 5, max: 6, score: 100},
            {min: 6, max: 7, score: 80},
            {min: 7, max: 8, score: 60},
            {min: 8, max: 9, score: 40},
            {min: 9, max: 10, score: 20}]

        //保存用户的客户端信息
        this.gameSessions = {};
    }

    //广播消息
    broadMsg(roomId, ret){
        let sessionInfo = this.gameSessions[roomId];
        log.info('========broadMsg======',sessionInfo.length)
        if(sessionInfo){
            for (let i = 0; i < sessionInfo.length; i++) {
                let cfg = sessionInfo[i];
                let client = cfg.client;
                client.send(JSON.stringify(ret));
            }
        }
    }

    addClientInfo(uid,client,roomId){
        let user = new UserClient(uid,client);

        if(!this.gameSessions[roomId]){
            this.gameSessions[roomId]  = [];
        }

        let isHava = false;
        for (let i = 0; i < this.gameSessions[roomId].length; i++) {
            if(this.gameSessions[roomId][i].uid === uid){
                isHava = true;
                break;
            }
        }
        if(!isHava){
            this.gameSessions[roomId].push(user);
        }else{
            this.updateClient(roomId,uid,client);
        }
    }

    updateClient(roomId, uid, client){
        let roomInfo = this.gameSessions[roomId];
        if(roomInfo){
            for (let i = 0; i < roomInfo.length; i++) {
                if(roomInfo[i].uid === uid){
                    roomInfo[i].client = client;
                    break;
                }
            }
        }
    }

    getSessionByRoomID(roomId){
        return this.gameSessions[roomId];
    }

    //判断开始
    async pd_start(uid,gameType,roomId){
        let userInfos = this.gameSessions[roomId];


            let ret = {
                type: CmdZt.ThemeMatchGameBroad,
                data:{
                    users:[], //用户数据
                    topics:[],//题目数据
                }
            }

            //取房间信息
            let roomInfo = await global.gameSerMgr.gameRedis.get_redis_in_room_list_zt_by_roomid(roomId);
            let uids = roomInfo.players;
            log.info('======uids==========',uids);
            //取用户数据
            if(uids){
                for (let i = 0; i < uids.length; i++) {
                    let userCur = await global.gameSerMgr.gameRedis.get_redes_in_gameInfo_list_zt_info(uids[i], gameType);
                    let user = {
                        userId: userCur.uid,
                        avator: userCur.avator,
                        score : userCur.score,
                    }
                    ret.data.users.push(user);
                }
            }

            //题目数据
            let topics = await gameMode.getTips(this.maxGroupCount,gameType,uid);
            log.error("======topics=======",topics)

            if(topics){
                for (let i = 0; i < topics.length; i++) {
                    let temp = {
                        tidx : i,
                        //时间限制
                        time : this.astrictTime,
                        //题目id
                        topicId : topics[i],
                    }
                    ret.data.topics.push(temp);
                }
            }

            //广播开始场景
            this.broadMsg(roomId,ret);
    }

    //广播两个用户信息
    async broadGameUserScenes(roomId){
        //取room_list_zts 列表里面指定房间号信息
        let roomInfo = await global.gameSerMgr.gameRedis.get_redis_in_room_list_zt_by_roomid(roomId);
        let ret = {
            type: CmdZt.ThemeMatchGameBroad,
            data: {
                userList:[],
            }
        }
        let players = roomInfo.players;
        let gametype = roomInfo.gameTypeZt;
        log.info('=======players======',players);
        if(players){
            let gameInfoList = await redisBase.getGameListZt();
            for (let i = 0; i < players.length ; i++) {
                log.info('=====get_redes_in_gameInfo_list_zt_info111==========',players[i],gametype);
                for (let j = 0; j < gameInfoList.length; j++) {
                    let gameInfo = JSON.parse(gameInfoList[j]);
                    if(gameInfo.uid === players[i] && gameInfo.gamType === gametype){
                        let temp = {
                            userId:gameInfo.uid,
                            name:gameInfo.name,
                            avator:gameInfo.avator,
                            rank:gameInfo.dwRank,
                            dwType:gameInfo.dwType,
                            dwLvType:gameInfo.dwType,
                            dwLv:gameInfo.dwLv,
                            winCount:gameInfo.countWin,
                        }
                        ret.data.userList.push(temp);
                        break;
                    }
                }
            }

            //广播两个玩家信息
            this.broadMsg(roomId,ret);
        }
    }

    //用户进入
    async on_user_entet(data,ctype,client){
        let uid = data.userId;
        let gameType = data.type;
        log.warn("=======on_user_entet=======",uid);

        client.pathname = uid;

        let ret = {
            type: ctype,
            data:{
                code: Respones.OK,
            }
        }

        //从gameInfo_list_zt 取房间号
        let gameInfo = await global.gameSerMgr.gameRedis.get_redes_in_gameInfo_list_zt_info(uid,gameType);
        if(gameInfo){
            let roomId = gameInfo.roomId;
            this.addClientInfo(uid,client,roomId);

            let userInfos = this.gameSessions[roomId];
            //表示两个玩家都进入了
            if(userInfos.length === 2) {
                setTimeout(() => {
                    this.broadGameUserScenes(roomId);
                }, 500);
            }
        }else{
            log.error('=======gameInfo_list_zt= 不存在 uid = ', uid, ' 主题类型 = ', gameType)
        }
    }

    //用户准备
    async on_user_reday(data,ctype,client){
        let uid = data.userId;
        let gameType = data.type;

        let ret = {
            type: ctype,
            data:{
                code: Respones.OK,
                uid: uid,
                status: 0 // 0是未准备 1是准备
            }
        }

        //从gameInfo_list_zt 取房间号
        let gameInfo = await global.gameSerMgr.gameRedis.get_redes_in_gameInfo_list_zt_info(uid,gameType);
        let roomId = gameInfo.roomId;

        //更新client
        this.updateClient(roomId,uid,client);

        let sessionInfo = this.gameSessions[roomId];
        for (let i = 0; i < sessionInfo.length; i++) {
            let tmp = sessionInfo[i];
            if(tmp.uid === uid){
                tmp.reday = true;
                ret.data.status = 1;
                break;
            }
        }

        let isAllReady = 0;
        //广播玩家准备状态
        for (let i = 0; i < sessionInfo.length; i++) {
            let tmp = sessionInfo[i];
            if(tmp.reday === true){
                isAllReady++;
            }
            let client = tmp.client;
            client.send(JSON.stringify(ret));
        }

        //两个玩家都准备完毕开始游戏
        if(isAllReady === sessionInfo.length){
                //广播开始游戏
                let res1 = {
                    type: CmdZt.ThemeMatchGameSceneBroad,
                    data:{
                        users:[],
                        topics:[],
                    }
                }

                //取房间信息
                let roomInfo = await global.gameSerMgr.gameRedis.get_redis_in_room_list_zt_by_roomid(roomId);
                let uids = roomInfo.players;
                log.info('======uids==========',uids);
                //取用户数据
                if(uids){
                    let gameList = await redisBase.getGameListZt();
                    for (let i = 0; i < uids.length; i++) {
                        for (let j = 0; j < gameList.length; j++) {
                            let userCur =  JSON.parse(gameList[j]);
                            if (userCur.uid === uids[i] && userCur.gamType === gameType){
                                let user = {
                                    userId: userCur.uid,
                                    avator: userCur.avator,
                                    score: userCur.score
                                }
                                res1.data.users.push(user);

                                //清空两个玩家的游戏记录数据
                                await global.gameSerMgr.gameRedis.clearMyRecord(userCur.uid);
                                break;
                            }
                        }
                    }
                }
                log.info('======,res1.data.users==========',res1.data.users);
                //题目数据
                let topics = await gameMode.getTips(this.maxGroupCount,gameType,uid);
                log.error("======topics=======",topics)
                if(topics){
                    for (let i = 0; i < topics.length; i++) {
                        let temp = {
                            tidx : i,
                            //时间限制
                            time : this.astrictTime,
                            //题目id
                            topicId : topics[i],
                        }
                        res1.data.topics.push(temp);
                    }
                }

                log.info('========res1111===========',res1);
                //广播玩家准备状态
                this.broadMsg(roomId,res1);
            }
    }

    //用户答题
    async on_user_answer(data,ctype,client){
        log.warn('============on_user_answer==========');
        let uid = data.userId; //用户id
        let topicId = data.topicId; //题目id
        let choiceId = data.choiceId; //用户选择的答案
        let costTime = data.costTime; //用户答题耗时
        let gameType = data.gameType;
        let roomId = 0;

        //从gameInfo_list_zt 取房间号
        let gameInfo = await global.gameSerMgr.gameRedis.get_redes_in_gameInfo_list_zt_info(uid,gameType);
        if(gameInfo){
            roomId = gameInfo.roomId;
        }
        log.warn('===========从gameInfo_list_zt 取房间号==========',gameInfo.roomId);

        let roomInfo = ModeZt.getRoomInfo(roomId);
        roomInfo.setRoomUser(uid, client);
        roomInfo.answerlen++;

        //更新client
        this.updateClient(roomId,uid,client);

        let ret = {
            type: ctype,
            data:{
                code: Respones.OK,
                //答题用户的uid
                uid: uid,
                //状态 0是未答题 1是答对 2是答错
                status : 0,
                //题目id
                tid : topicId,
                //自己选择的答案id,默认从1开始,例如： 1 2 3 4 表示 答案 1 2 3 4
                cid : choiceId,

                userInfo:{
                    userId: uid,
                    score : 0,
                }
            }
        }

        //记录我答题总数
        log.warn('======记录我答题总数========');
        await ModeZt.updateAnswerZtTotal(uid,gameType);
        log.warn('======记录我答题总数 end========');

        let topicCfg = gameCom.getItemById(topicId);
        log.info('====topicCfg=====',topicCfg.ID)
        if(topicCfg.Answer === choiceId){
            log.warn('======答对题目========');
            ret.data.status = gameCfg.Answer.Cur;
            //记录答对的题目数
            log.warn('======记录答对的题目数========');
            await ModeZt.updateAnswerZtTrue(uid,gameType);
            log.warn('======记录答对的题目数2========');

            //记录用户答d对的题目
            log.warn('======记录用户答d对的题目========');
            await ModeZt.recordAnswerTrue(uid,topicId);
            log.warn('======记录用户答d对的题目2========',topicId);

            // 设置得分逻辑
            let addScore = 0;
            for (let i = this.timeCfg.length - 1; i >= 0; i--) {
                let cfg = this.timeCfg[i];
                if(costTime >= cfg.min && costTime <= cfg.max){
                    addScore += cfg.score;
                    break;
                }
            }

            //记录当前用户答题耗时和得分
            roomInfo.setRoomUserTimeAnScore(uid,addScore,costTime);

            //更新用户的分数
            log.warn('======更新用户的分数========',addScore,topicId);
            let res = await ModeZt.updateUserScore(uid,gameType,addScore);
            log.warn("=======更新用户的分数 end========",res.uid)

            ret.data.userInfo.score = res.score;
            log.warn('======答对题目 end========');
        }else{
            log.warn('======答错题目========');
            ret.data.status = gameCfg.Answer.Err;
        }

        log.info('======判断两个人是否都答完毕=======',roomInfo.answerlen);
        //判断两个人是否都答完毕
        if(roomInfo.answerlen >= 2){
            roomInfo.answerlen = 0;

            //记录当前房间答完一道题目
            roomInfo.topicLen++;

            log.info('======广播当前题目结果=======',topicId,topicCfg.Answer);
            //广播当前题目结果
            let gameSession = this.getSessionByRoomID(roomId);
            gameZtOpt.broadCurTopicEnd(topicCfg.Answer,gameSession,roomId);
            log.info('======广播当前题目结果1=======');

            //判断结算
            log.info('=========判断结算==========',roomInfo.topicLen,this.maxGroupCount);
            if(roomInfo.topicLen >= this.maxGroupCount){
                log.info('========当前轮结算=======')
                gameZtEnd.broadGammEndCur(uid,gameType,roomInfo,roomId,client,gameSession);
                log.info('========当前轮结算2=======')
            }else{
                //广播下一题
                log.info('========广播下一题=======');
                gameZtOpt.broadNextTopic(roomInfo,gameSession);
                log.info('========广播下一题2=======');
            }
        }

        log.info('======保存我当前答题1=======');
        //保存我当前答题
        let item = new TopicCur(ret.data.uid,ret.data.status,ret.data.tid,ret.data.cid);
        if(this.gameSessions){
            for (let i = 0; i <  this.gameSessions[roomId].length; i++) {
                if(this.gameSessions[roomId][i].uid === uid){
                    this.gameSessions[roomId][i].curData = item;
                }
            }
        }

        log.info('======记录我答的题目,方便会看回放记录=======');
        //记录我答的题目,方便会看回放记录
        let d = {
            idx:new Date().getTime(),
            uid: ret.data.uid,
            status: ret.data.status, //0是未答题 1是答对 2是答错
            tid: ret.data.tid,
            cid: ret.data.cid,
        };
        await global.gameSerMgr.gameRedis.saveMyRecord(uid, JSON.stringify(d));

        //返回用户答题结果
        log.error('======返回用户答题结果=======');
        client.send(JSON.stringify(ret));
    }

    //下一组题目
    async on_next_group(data,ctype,client){
        let uid = data.userId;
        let gameType = data.gameType;
        log.info("========on_next_group===========");
        let info = await global.gameSerMgr.gameRedis.get_redes_in_gameInfo_list_zt_info(uid,gameType);
        log.info("========on_next_group2===========");

        let roomId = info.roomId;
        let players = null;
        let gameTypeZt = null;

        //step：删除room_list_zts
        let roomList = await redisBase.getValidRoomInList();
        log.info("========on_next_group3===========");
        if(roomList){
            for (let i = 0; i < roomList.length; i++) {
                let roomCfg = JSON.parse(roomList[i]);
                if(roomCfg.roomId === roomId){
                    log.info("====getValidRoomInList1111========",i);
                    players = roomCfg.players;
                    gameTypeZt = roomCfg.gameTypeZt;
                    await redisBase.delRooomList(i,JSON.stringify(roomCfg));
                    break;
                }
            }
        }

        log.info("========on_next_group=4===========");
        log.info("========删除gameInfo_list_zt===========",players);
        let gameList = await redisBase.getGameListZt();
        if(players && gameTypeZt){
            //step２：删除gameInfo_list_zt 列表里面的roomId 参数
            for (let i = 0; i < players.length ; i++) {
                let uidCur = players[i];
                for (let j = 0; j < gameList.length; j++) {
                    let gameCfg = JSON.parse(gameList[j]);
                    if(gameCfg.uid === uidCur && gameCfg.gamType === gameTypeZt){
                        gameCfg.roomId = 0;
                        await redisBase.updateGameListTzValue(j,JSON.stringify(gameCfg));
                        break;
                    }
                }

                // step3:删除 record_list_zt_ 记录
                await global.gameSerMgr.gameRedis.clearMyRecord(uidCur);
            }
        }

        log.info("========删除gameInfo_list_zt end===========");
        log.info('======on_next_group=1======');
        let ret = {
            type: ctype,
            data:{}
        }
        log.info('======on_next_group end=======',ret);
        client.send(JSON.stringify(ret));
    }

    //当前轮记录
    async on_game_record(data,ctype,client){
        let uid = data.userId;
        let list = await global.gameSerMgr.gameRedis.getMyRecordList(uid)
        let list1 = [];
        for (let i = 0; i < list.length; i++) {
            list1.push(JSON.parse(list[i]));
        }
        list1.sort((a,b)=>{
            return a.idx -b.idx;
        })

        let ret = {
            type: ctype,
            data:{
                list:[]
            }
        }
        log.info("=======on_game_record=======",list1);
        for (let i = 0; i < list1.length; i++) {
            let item = list1[i];
            let temp = {
                uid: item.uid,
                status: item.status, //0是未答题 1是答对 2是答错
                tid: item.tid,
                cid: item.cid,
            }
            ret.data.list.push(temp);
        }
        client.send(JSON.stringify(ret));
    }

    //领取段位结算奖励
    async on_get_dw_end_reward(data,ctype,client){
        let uid = data.userId;
        let bei = data.bei;


        let gameType = null;
        let rList = await redisBase.getValidRoomInList();
        for (let i = 0; i < rList.length; i++) {
            let cfg = JSON.parse(rList[i]);
            if(cfg.players.indexOf(uid) !== -1){
                gameType = cfg.gameTypeZt;
                break;
            }
        }

        let xmNumCost = 0;
        let gList = await redisBase.getGameListZt();
        for (let i = 0; i < gList.length; i++) {
            let cfg =  JSON.parse(gList[i]);
            if(cfg.uid === uid && gameType && cfg.gamType === gameType){
                xmNumCost = cfg.xzNumCost;
                break;
            }
        }

        let res =  AlgorZt.updateDwLv(xmNumCost);
        log.info('===========段位奖励的数据============',res);
        if(res.rdType === gameCfg.RewardType.TYpe_QiuNum){
            let user = await redisBase.getUserInfo(uid);
            log.info('===========段位奖励的数据1============',user);
            if(user){
                user.ballNum =  user.ballNum*1 + res.reward;
            }
            log.info('===========段位奖励的数据2============',user);
            await redisBase.setUserInRedis(user);
        }

        log.info('===========段位奖励 end============');
        let ret = {
            type: ctype,
            data:{
                code:Respones.OK
            }
        }
        client.send(JSON.stringify(ret));
    }

    //用户答题超时
    async on_user_answer_outtime(data,ctype,client){
        let uid = data.userId;
        let topicId = data.tid;

        let ret = {
            type: ctype,
            data:{
                code: Respones.OK,
                //答题用户的uid
                uid: uid,
                //状态 0是未答题 1是答对 2是答错
                status : 0,
                //题目id
                tid : topicId,
                //自己选择的答案id,默认从1开始,例如： 1 2 3 4 表示 答案 1 2 3 4
                cid:0,
            }
        }

        let gameType = null;
        let rList = await redisBase.getValidRoomInList();
        for (let i = 0; i < rList.length; i++) {
            let cfg = JSON.parse(rList[i]);
            if(cfg.players.indexOf(uid) !== -1){
                gameType = cfg.gameTypeZt;
                break;
            }
        }
        
        let roomId = null;
        let gameInfo = await global.gameSerMgr.gameRedis.get_redes_in_gameInfo_list_zt_info(uid,gameType);
        if(gameInfo){
            roomId = gameInfo.roomId;

            log.warn('===========从gameInfo_list_zt11 取房间号==========',gameInfo.roomId);

            let roomInfo = ModeZt.getRoomInfo(roomId);
            roomInfo.setRoomUser(uid, client);
            roomInfo.answerlen++;

            //记录当前用户答题耗时和得分
            roomInfo.setRoomUserTimeAnScore(uid,0,10);
            //更新client
            this.updateClient(roomId,uid,client);

            //保存我当前答题
            let item = new TopicCur(ret.data.uid,ret.data.status,ret.data.tid,ret.data.cid);
            if(this.gameSessions){
                for (let i = 0; i <  this.gameSessions[roomId].length; i++) {
                    if(this.gameSessions[roomId][i].uid === uid){
                        this.gameSessions[roomId][i].curData = item;
                    }
                }
            }

            log.info('======记录我答的题目,方便会看回放记录=======');
            //记录我答的题目,方便会看回放记录
            let d = {
                idx:new Date().getTime(),
                uid: ret.data.uid,
                status: ret.data.status, //0是未答题 1是答对 2是答错
                tid: ret.data.tid,
                cid: ret.data.cid,
            };
            await global.gameSerMgr.gameRedis.saveMyRecord(uid, JSON.stringify(d));

            let topicCfg = gameCom.getItemById(topicId);
            if(roomInfo.answerlen >= 2){
                roomInfo.answerlen = 0;

                //记录当前房间答完一道题目
                roomInfo.topicLen++;

                log.info('======广播当前题目结果11=======',topicId,topicCfg.Answer);
                //广播当前题目结果
                let gameSession = this.getSessionByRoomID(roomId);
                gameZtOpt.broadCurTopicEnd(topicCfg.Answer,gameSession,roomId);
                log.info('======广播当前题目结果12=======');

                //判断结算
                log.info('=========判断结算==========',roomInfo.topicLen,this.maxGroupCount);
                if(roomInfo.topicLen >= this.maxGroupCount){
                    log.info('========当前轮结算=======')
                    gameZtEnd.broadGammEndCur(uid,gameType,roomInfo,roomId,client,gameSession);
                    log.info('========当前轮结算2=======')
                }else{
                    //广播下一题
                    log.info('========广播下一题=======');
                    gameZtOpt.broadNextTopic(roomInfo,gameSession);
                    log.info('========广播下一题2=======');
                }
            }
        }

        client.send(JSON.stringify(ret));
    }

    //用户退出房间
    async on_user_exit_game(data,ctype,client){
        let uid = data.userId;
        log.info('=====清空room_list_zts=========',uid);

        let gType = 0;
        let players = null;
        let roomId = 0;
        let rList = await redisBase.getValidRoomInList();
        for (let i = 0; i < rList.length; i++) {
            let cfg = JSON.parse(rList[i]);
            let idx = cfg.players.indexOf(uid);
            if(idx !== -1){
                players = cfg.players;
                gType = cfg.gameTypeZt;
                roomId = cfg.roomId;
                break;
            }
        }

        log.info('======on_user_exit_game===========',players);
        if(players){
            //step1： 修改 gameInfo_list_zt 的房间号
            log.info('======step1： 修改 gameInfo_list_zt 的房间号===========');
            for (let i = 0; i < players.length; i++) {
                let uidCur = players[i];
                await common.set_gameInfo_list_zt_roomId(uidCur,gType,0);
            }

            //step2：清空room_list_zts
            log.info('======step2：清空room_list_zts===========');
            for (let i = 0; i < players.length; i++) {
                let uidCur = players[i];
                await common.clearRs_roomListZt(uidCur);
            }

            //step3:清空当前记录
            log.info('======/step3:清空当前记录===========');
            // for (let i = 0; i < players.length; i++) {
            //     let uidCur = players[i];
            //     await global.gameSerMgr.gameRedis.clearMyRecord(uidCur);
            // }
        }

        log.info('=====清空room_list_zts= end========');

        //step4: 广播退出结果
        log.info('=====step4: 广播退出结果========');
        let ret = {
            type: ctype,
            data:{
                code:Respones.OK
            }
        }
        this.broadMsg(roomId,ret);
    }
}

module.exports = GameZt.getInstance();